import 'dart:convert';
import 'dart:ui';

import 'package:local_auth_android/local_auth_android.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:jpush_flutter/jpush_flutter.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:local_auth/local_auth.dart';
import 'package:moment_dart/moment_dart.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:spendbook/deposit/set.dart';
import 'package:spendbook/finance/set.dart';
import 'package:spendbook/login.dart';
import 'package:spendbook/models/user.dart';
import 'package:spendbook/my/about.dart';
import 'package:spendbook/my/category.dart';
import 'package:spendbook/my/chart.dart';
import 'package:spendbook/my/family.dart';
import 'package:spendbook/my/qrcode.dart';
import 'package:spendbook/my/scan.dart';
import 'package:spendbook/my/setting.dart';
import 'common/constants.dart';

import 'record/list.dart';
import 'record/add.dart';

import 'finance/list.dart';
import 'deposit/list.dart';
import 'my/index.dart';

Future<User> _requestUser() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  User _user = User.fromTheme(prefs.getString('themeMode') ?? 'pink');
  _user.needBiometrics = prefs.getBool('needBiometrics') ?? false;
  if (prefs.containsKey('user')) {
    _user.fromJson(await JsonDecoder().convert(prefs.getString('user') ?? '{}'));
  }

  if (_user.isLogin) {
    await _user.fetchOne();
  }
  return _user;
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterDownloader.initialize();
  User _user = await _requestUser();
  Moment.setGlobalLocalization(MomentLocalizations.zhCn());
  return runApp(ChangeNotifierProvider(create: (_) => _user, child: App()));
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final user = context.watch<User>();
    ThemeData _theme = themeList[user.themeMode]['getTheme'](context);
    return RefreshConfiguration(
        child: MaterialApp(
            title: '家庭理财簿',
            theme: _theme,
            initialRoute: '/',
            localizationsDelegates: [
              RefreshLocalizations.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
            ],
            supportedLocales: [Locale.fromSubtags(languageCode: 'zh'), Locale.fromSubtags(languageCode: 'en')],
            routes: {
              '/record/add': (context) => AddRecordScreen(),
              '/record/view': (context) => ViewRecordScreen(),
              '/finance/add': (context) => AddFinanceScreen(),
              '/finance/set': (context) => SetFinanceScreen(),
              '/finance/view': (context) => ViewFinanceScreen(),
              '/deposit/add': (context) => AddDepositScreen(),
              '/deposit/set': (context) => SetDepositScreen(),
              '/deposit/view': (context) => ViewDepositScreen(),
              '/scan': (context) => ScanScreen(),
              '/setting': (context) => SettingScreen(),
              '/about': (context) => AboutScreen(),
              '/category': (context) => CategoryScreen(),
              '/family': (context) => FamilyScreen(),
              '/qrcode': (context) => QrCodeScreen(),
              '/chart': (context) => ChartScreen()
            },
            home: user.isLogin ? HomeScreen(user: user) : LoginScreen()));
  }
}

class HomeScreen extends StatefulWidget {
  HomeScreen({Key? key, required this.user}) : super(key: key);

  final User user;

  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
  AppLifecycleState? _notification;
  DateTime? lastDatetime;

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    _notification = state;
    if (state == AppLifecycleState.resumed) {
      if (lastDatetime != null && DateTime.now().difference(lastDatetime!).inMinutes > 5) {
        _verifyBiometrics();
      }
    } else if (state == AppLifecycleState.inactive) {
      lastDatetime = DateTime.now();
    }
  }

  final jPush = new JPush();
  int _selectedIndex = 0;
  final List<Widget> _widgetList = <Widget>[RecordScreen(), FinanceScreen(), DepositScreen(), MyScreen()];
  final LocalAuthentication _localAuthentication = LocalAuthentication();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _addNotificationListener();
    _verifyBiometrics();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  _verifyBiometrics() async {
    final _user = context.read<User>();
    if (!_user.needBiometrics) return;
    bool isSupport = await _localAuthentication.isDeviceSupported();
    if (!isSupport) return;
    bool authenticated = false;
    try {
      authenticated = await _localAuthentication.authenticate(
          localizedReason: '立即解锁',
          authMessages: const <AuthMessages>[
            AndroidAuthMessages(
              signInTitle: '解锁访问应用',
              biometricHint: '指纹认证',
              cancelButton: '取消',
            ),
          ],
          options: const AuthenticationOptions());
      if (!authenticated) {
        _verifyBiometrics();
      }
    } catch (e) {
      print('报错:' + e.toString());
    }
  }

  _addNotificationListener() async {
    String registrationId = await jPush.getRegistrationID();
    if (widget.user.pushId != registrationId) {
      widget.user.pushId = registrationId;
      widget.user.store();
    }
    jPush.addEventHandler(onReceiveNotification: (Map<String, dynamic> notification) async {
      print("收到推送提醒: $notification");
      if ([null, AppLifecycleState.inactive, AppLifecycleState.resumed].contains(_notification)) {
        final res = await showOkCancelAlertDialog(
          context: context,
          title: '收到新的提醒',
          message: notification['alert'],
        );
        if (res == OkCancelResult.ok) {
          _openNotification(notification);
          jPush.clearNotification(notificationId: notification['extras']['cn.jpush.android.NOTIFICATION_ID']);
        }
      }
    }, onOpenNotification: (Map<String, dynamic> notification) async {
      print("打开了推送提醒: $notification");
      _openNotification(notification);
    });
  }

  _openNotification(Map<String, dynamic> notification) {
    final Map<String, dynamic> _data = JsonDecoder().convert(notification['extras']['cn.jpush.android.EXTRA']);
    switch (_data['type']) {
      case 'record':
        Navigator.of(context).pushNamed('/record/view', arguments: _data);
        break;
      case 'project':
        Navigator.of(context).pushNamed('/finance/view', arguments: _data);
        break;
      case 'card':
        Navigator.of(context).pushNamed('/deposit/view', arguments: _data);
        break;
    }
  }

  Future<bool> _onWillPop() async {
    final res = await showDialog(
      context: context,
      builder: (context) => new AlertDialog(
        title: new Text('你确定吗?'),
        content: new Text('你确定要退出该应用吗?'),
        actions: <Widget>[
          new TextButton(
            onPressed: () => Navigator.of(context).pop(false),
            child: new Text('否'),
          ),
          new TextButton(
            onPressed: () => SystemNavigator.pop(),
            child: new Text('是'),
          ),
        ],
      ),
    );
    return res;
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
        canPop: false,
        child: Scaffold(
          body: _widgetList.elementAt(_selectedIndex),
          bottomNavigationBar: BottomNavigationBar(
            items: choices
                .map((choice) => BottomNavigationBarItem(
                      icon: Icon(choice.icon),
                      label: choice.title,
                    ))
                .toList()
              ..add(
                BottomNavigationBarItem(
                  icon: Icon(Icons.account_circle),
                  label: '我',
                ),
              ),
            type: BottomNavigationBarType.fixed,
            currentIndex: _selectedIndex,
            onTap: (int index) {
              setState(() {
                _selectedIndex = index;
              });
            },
          ),
        ),
        onPopInvoked: (bool didPop) {
          if (didPop) {
            return;
          }
          _onWillPop();
        });
  }
}
